#ifndef CLOUDVIEWER_H
#define CLOUDVIEWER_H

// for solving error: no override found for 'vtkRenderWindow'
#include <vtkAutoInit.h>
// VTK_MODULE_INIT(vtkRenderingOpenGL2);
// VTK_MODULE_INIT(vtkInteractionStyle);

#include "MyCloud.h"
#include "groove_detection.h"
#include "scratch_detection.h"
#include "ptPicking.h"
#include "planfit.h"
#include "sphereFit.h"
#include <pcl/io/obj_io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/vtk_io.h>
#include <pcl/io/vtk_lib_io.h> // loadPolygonFileOBJ
#include <pcl/ModelCoefficients.h>
#include <pcl/PolygonMesh.h>
#include <pcl/common/transforms.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/common/common.h>
#include <pcl/visualization/pcl_visualizer.h>

#include <Eigen/Core>
#include <Eigen/Geometry>

// Boost
#include <boost/math/special_functions/round.hpp>

#include "AboutWin.h"
#include "FileIO.h"
#include "GBK.h"
#include "Tools.h"
#include "ui_CloudViewer.h"
#include <QtWidgets/QMainWindow>

#include "QVTKWidget.h"
#include <QAction>
#include <QColorDialog>
#include <QDebug>
#include <QDesktopServices>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QInputDialog>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QMouseEvent>
#include <QStatusBar>
#include <QString>
#include <QTextEdit>
#include <QTime>
#include <QToolBar>
#include <QUrl>
#include <QVBoxLayout>
#include <QtWidgets/QMainWindow>
#include <algorithm>
#include <map>
#include <vector>
#include <vtkRenderWindow.h>

typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloudT;

const int CLOUDVIEWER_THEME_WINDOWS = 0;
const int CLOUDVIEWER_THEME_DARCULA = 1;

const int CLOUDVIEWER_LANG_ENGLISH = 0;
const int CLOUDVIEWER_LANG_CHINESE = 1;

const int CLOUDVIEWER_MODE_POINT = 0;
const int CLOUDVIEWER_MODE_MESH = 1;
const int CLOUDVIEWER_MODE_POINT_MESH = 2;

using std::map;
using std::string;
using std::vector;

class CloudViewer : public QMainWindow {
  Q_OBJECT

public:
  CloudViewer(QWidget *parent = 0);
  ~CloudViewer();

protected:
  /** @brief 0 = x | 1 = y | 2 = z */
  int filtering_axis_;

  /** @brief Holds the color mode for @ref colorCloudDistances */
  int color_mode_;

  /** @brief Color point cloud on X,Y or Z axis using a Look-Up Table (LUT)
   * Computes a LUT and color the cloud accordingly, available color palettes
   * are :
   *
   *  Values are on a scale from 0 to 255:
   *  0. Blue (= 0) -> Red (= 255), this is the default value
   *  1. Green (= 0) -> Magenta (= 255)
   *  2. White (= 0) -> Red (= 255)
   *  3. Grey (< 128) / Red (> 128)
   *  4. Blue -> Green -> Red (~ rainbow)
   *
   * @warning If there's an outlier in the data the color may seem uniform
   * because of this outlier!
   * @note A boost rounding exception error will be thrown if used with a non
   * dense point cloud
   */
  void colorCloudVecDistances();
  void colorCloudDist(int cloud_id);
  void areaPicking_callback(const pcl::visualization::AreaPickingEvent &event,
                            void *args);

private:
  Ui::CloudViewerClass ui;
  pcl::PointCloud<pcl::PointXYZ>::Ptr xyzCloud;
  MyCloud mycloud;
  MyCloud mycloudSelected;    //被框选的点云
  int selected_num = 0;    //某个点云被框选的点云的编号（计数，被框选了几次）
  int cloudselect_id = 0;
  std::vector<MyCloud> mycloud_vec;
  boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer_;

  FileIO fileIO;

  QString save_filename;
  long total_points = 0; // Total amount of points in the viewer

  unsigned int red = 255;
  unsigned int green = 255;
  unsigned int blue = 255;
  unsigned int p = 2;
  std::vector<int> pointcolor;
  std::vector<int> bgcolor;

  QVBoxLayout *layout;

  int theme_id = 0;             // 0: Windows theme, 1: Darcula theme
  bool enable_console = true;   // console 的可用状态
  QString timeCostSecond = "0"; // 记录某个动作执行的时间

  /***** Slots of QMenuBar and QToolBar *****/
  // File menu slots
  void open();
  void add();
  void doOpen(const QStringList &filePathList);
  void clear();

  void savemulti(const QFileInfo &fileInfo, bool isSaveBinary);
  void exit();
  // Display menu slots
  void pointcolorChanged();
  void bgcolorChanged();
  void mainview();
  void leftview();
  void topview();
  void resetview();
  // Process menu slots
  int areaPicking();     //框选点云
  int scratchDetection(); //划痕检测
  int grooveDetection(); //沟槽检测
  int planFit(); //平面拟合
  int heightDiff(); // 计算高度差
  int sphereFit();  //球面拟合

  // About menu slots
  void about();
  void help();

  /***** Utils Methods ***/
  void initial();
  void showPointcloud();                   //显示点云
  void showPointcloudAdd();                //添加给viewer，显示点云
  void showPointcloudNew(int cloudPre_ID); //显示新增的点云

  void setCloudColor(unsigned int r, unsigned int g, unsigned int b);

  void setPropertyTable();
  void setConsoleTable();

  void consoleLog(QString operation, QString subname, QString filename,
                  QString note);

public slots:
  void save();
  void changeTheme();
  void changeLanguage();

  void colorBtnPressed();

  void RGBsliderReleased();
  void psliderReleased();
  void pSliderChanged(int value);

  // Slots of checkBox
  void cooCbxChecked(int value);
  void bgcCbxChecked(int value);

  /***** Slots of dataTree(QTreeWidget) widget *****/
  // Item in dataTree is left-clicked
  void itemSelected(QTreeWidgetItem *, int);
  // Item in dataTree is right-clicked
  void popMenu(const QPoint &);
  void hideItem();
  void showItem();
  void deleteItem();

  // set show mode
  void setRenderingMode();

  void popMenuInConsole(const QPoint &);
  void clearConsole();
  void enableConsole();
  void disableConsole();

  void debug(const string &s);

  /** @brief Triggered whenever a button in the "Color on axis" group is clicked
   */
  void axisChosen();

  /** @brief Triggered whenever a button in the "Color mode" group is clicked */
  void lookUpTableChosen();
};

#endif // CLOUDVIEWER_H
